package com.bvbot.core.order;

import static com.bvbot.core.Logger.log;

import java.math.BigDecimal;

import com.bvbot.core.session.BalanceResponse;
import com.bvbot.core.session.BvSession;
import com.bvbot.core.session.BvSessionException;
import com.bvbot.core.session.MarketResponse;
import com.bvbot.core.session.SaleResponse;

public class SecuritySeller extends AbstractOrderGiver {

	private boolean gold;

	public SecuritySeller(boolean isGold) {
		this.setGold(isGold);
	}

	private String getSecurity() {
		return isGold() ? "gold" : "silver";
	}

	public void sellRatio(float ratio) {
		log("Sell " + ratio + "/1 of " + getSecurity() + " - START");
		int numberOfGramsToSell = 0;
		try {
			BvSession session = new BvSession();
			session.start();
			numberOfGramsToSell = computeGramsToSell(session, ratio);
			sellGrams(numberOfGramsToSell);
		} catch (Exception e) {
			log("Exception occured in " + getSecurity() + " sale : "
					+ e.getMessage(), e);
		}
		log("Sell " + ratio + "/1 of " + getSecurity() + " - STOP");
	}

	public void sellGrams(int gramsNumber) {
		log("sellGrams : " + gramsNumber + " to sell . START");
		boolean allIsSold = (gramsNumber == 0);
		Sale sale = new Sale(gramsNumber, 0);
		while (!allIsSold) {
			try {
				BvSession session = new BvSession();
				session.start();
				doBestSale(sale, session);
				if (sale.allIsSold()) {
					allIsSold = true;
				}
			} catch (Exception e) {
				log("Exception occured in " + getSecurity() + " sale : "
						+ e.getMessage(), e);
			}
		}
		log("sellGrams : " + gramsNumber + " to sell . END");
	}

	private void doBestSale(Sale sale, BvSession session)
			throws BvSessionException {
		boolean workToDo = true;
		while (workToDo) {
			doSale(sale, session);
			if (sale.allIsSold()) {
				workToDo = false;
			}
		}
		log("Sale of " + sale.getGramsToSell() + " grams finished : "
				+ sale.getGramsSold() + " grams sold.");
	}

	private void doSale(Sale sale, BvSession session) throws BvSessionException {
		MarketResponse mr = null;
		if (isGold()) {
			mr = session.getGoldMarket();
		} else {
			mr = session.getSilverMarket();
		}
		BigDecimal marketBidPrice = mr.computeHighestBuyPrice();
		SaleResponse sr = session.sell(marketBidPrice,
				sale.getNextOfferGramNumber(), isGold());
		int gramsSold = sr.getGramsSold();
		sale.declareSoldGrams(gramsSold);
		log(sr.getSummary());
	}

	protected int computeGramsToSell(BvSession session, float ratio)
			throws BvSessionException {
		int result = -1;
		BalanceResponse response = session.getBalance();
		int gramsAvailable = 0;
		if (isGold()) {
			gramsAvailable = response.getGoldGrams();
		} else {
			gramsAvailable = response.getSilverGrams();
		}
		Float gramsToSell = gramsAvailable * ratio;
		result = gramsToSell.intValue();
		log("They are " + gramsAvailable
				+ " grams available. Given a ratio of " + ratio + ", " + result
				+ " grams will be sold.");
		return result;
	}

	public static void main(String[] args) {
		SecuritySeller seller = new SecuritySeller(true);
		seller.sellGrams(1);
	}

	private void setGold(boolean gold) {
		this.gold = gold;
	}

	public boolean isGold() {
		return gold;
	}
}
